package com.ltx.bugseeker.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import cn.dev33.satoken.stp.StpUtil;

import java.time.LocalDateTime;

/**
 * MyBatis Plus配置类
 * 配置分页插件、自动填充等功能
 * 
 * @author ltx
 * @since 2025-10-20 14:43:42
 */
@Slf4j
@Configuration
@EnableTransactionManagement
public class MybatisPlusConfig {
    
    /**
     * 配置MyBatis Plus拦截器
     * 主要用于分页功能
     * 
     * @return MyBatis Plus拦截器实例
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        log.info("初始化MyBatis Plus拦截器");
        
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        
        // 添加分页插件
        PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor();
        // 设置数据库类型为PostgreSQL
        paginationInterceptor.setDbType(DbType.POSTGRE_SQL);
        // 设置单页分页条数限制，默认无限制
        paginationInterceptor.setMaxLimit(1000L);
        // 开启count的join优化，只针对部分left join
        paginationInterceptor.setOptimizeJoin(true);
        
        interceptor.addInnerInterceptor(paginationInterceptor);
        
        log.info("MyBatis Plus拦截器初始化完成");
        return interceptor;
    }
    
    /**
     * 自动填充处理器
     * 用于自动填充创建时间、更新时间等字段
     * 
     * @return 自动填充处理器实例
     */
    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new AutoFillMetaObjectHandler();
    }
    
    /**
     * 自动填充处理器实现类
     * 实现字段的自动填充逻辑
     */
    @Slf4j
    public static class AutoFillMetaObjectHandler implements MetaObjectHandler {
        
        /**
         * 创建时间字段名
         */
        private static final String CREATE_TIME_FIELD = "createTime";
        
        /**
         * 更新时间字段名
         */
        private static final String UPDATE_TIME_FIELD = "updateTime";
        
        /**
         * 创建者字段名
         */
        private static final String CREATE_BY_FIELD = "createBy";
        
        /**
         * 更新者字段名
         */
        private static final String UPDATE_BY_FIELD = "updateBy";
        
        /**
         * 逻辑删除字段名
         */
        private static final String DELETED_FIELD = "deleted";
        
        /**
         * 项目所有者字段名
         */
        private static final String OWNER_ID_FIELD = "ownerId";
        
        /**
         * 插入时自动填充
         * 
         * @param metaObject 元对象，包含实体的元信息
         */
        @Override
        public void insertFill(MetaObject metaObject) {
            log.debug("开始插入填充...");
            
            LocalDateTime now = LocalDateTime.now();
            
            // 填充创建时间
            this.strictInsertFill(metaObject, CREATE_TIME_FIELD, LocalDateTime.class, now);
            
            // 填充更新时间
            this.strictInsertFill(metaObject, UPDATE_TIME_FIELD, LocalDateTime.class, now);
            
            // 填充逻辑删除字段，默认为0（未删除）
            this.strictInsertFill(metaObject, DELETED_FIELD, Integer.class, 0);
            
            // 填充创建者（从当前登录用户获取）
            Long currentUserId = getCurrentUserId();
            this.strictInsertFill(metaObject, CREATE_BY_FIELD, Long.class, currentUserId);
            
            // 填充更新者
            this.strictInsertFill(metaObject, UPDATE_BY_FIELD, Long.class, currentUserId);
            
            // 如果是项目实体，填充项目所有者
            if (metaObject.getOriginalObject().getClass().getSimpleName().equals("Project")) {
                this.strictInsertFill(metaObject, OWNER_ID_FIELD, Long.class, currentUserId);
            }
            
            log.debug("插入填充完成");
        }
        
        /**
         * 更新时自动填充
         * 
         * @param metaObject 元对象，包含实体的元信息
         */
        @Override
        public void updateFill(MetaObject metaObject) {
            
            LocalDateTime now = LocalDateTime.now();
            
            // 填充更新时间
            this.strictUpdateFill(metaObject, UPDATE_TIME_FIELD, LocalDateTime.class, now);
            
            // 填充更新者
            this.strictUpdateFill(metaObject, UPDATE_BY_FIELD, Long.class, getCurrentUserId());

        }
        
        /**
         * 获取当前用户ID
         * 从Sa-Token中获取当前登录用户的ID
         * 
         * @return 当前用户ID，如果未登录则返回null
         */
        private Long getCurrentUserId() {
            try {
                // 从Sa-Token中获取当前登录用户ID
                if (StpUtil.isLogin()) {
                    return StpUtil.getLoginIdAsLong();
                } else {
                    log.warn("用户未登录，无法获取用户ID");
                    return null;
                }
            } catch (Exception e) {
                log.warn("获取当前用户ID失败: {}", e.getMessage());
                return null;
            }
        }
    }
}